package cn.lingyangwl.agile.auth.third;

import cn.lingyangwl.agile.auth.model.rqrs.third.AuthUrlGetReq;
import cn.lingyangwl.agile.auth.model.rqrs.third.ThirdAuthResp;
import cn.lingyangwl.agile.auth.model.rqrs.third.ThirdAuthUser;
import cn.lingyangwl.agile.auth.model.rqrs.third.ThirdLoginReq;
import cn.lingyangwl.agile.auth.oauth2.model.RegisteredClient;
import cn.lingyangwl.agile.model.enums.ConfigDefineEnum;
import cn.lingyangwl.agile.model.module.auth.GrantTypeEnum;
import cn.lingyangwl.agile.model.module.config.ConfigInfo;
import cn.lingyangwl.agile.model.module.config.param.BaseConfigParam;
import cn.lingyangwl.agile.model.module.config.param.WxMpParam;
import cn.lingyangwl.framework.tool.core.StringUtils;
import cn.lingyangwl.framework.tool.core.exception.Assert;
import cn.lingyangwl.framework.tool.core.exception.BizException;
import me.zhyd.oauth.config.AuthConfig;
import me.zhyd.oauth.enums.scope.AuthWechatMpScope;
import me.zhyd.oauth.model.AuthCallback;
import me.zhyd.oauth.model.AuthResponse;
import me.zhyd.oauth.model.AuthUser;
import me.zhyd.oauth.request.AuthRequest;
import me.zhyd.oauth.request.AuthWeChatMpRequest;
import me.zhyd.oauth.utils.AuthStateUtils;
import org.springframework.stereotype.Component;

import java.util.Arrays;
import java.util.Collections;

/**
 * 微信h5授权登录
 *
 * @author shenguangyang
 */
@Component
public class WxMpAuth extends BaseThirdAuth {
    @Override
    public GrantTypeEnum grantType() {
        return GrantTypeEnum.WEIXIN_H5;
    }

    private AuthRequest getAuthRequest(String scope, RegisteredClient client, WxMpParam wxMpParam, String backUrl) {
        String returnUrl = wxMpParam.getAuthReturnUrl();
        String redirectUri = getThirdRedirectUri(returnUrl, backUrl, client);
        String newScope = StringUtils.defaultIfEmpty(scope, AuthWechatMpScope.SNSAPI_USERINFO.getScope());
        if (Arrays.stream(AuthWechatMpScope.values()).noneMatch(e -> e.getScope().equals(newScope))) {
            throw new BizException("scope 只支持 [{}、{}]",
                    AuthWechatMpScope.SNSAPI_USERINFO.getScope(), AuthWechatMpScope.SNSAPI_BASE.getScope());
        }
        return new AuthWeChatMpRequest(AuthConfig.builder()
                .clientId(wxMpParam.getAppId())
                .clientSecret(wxMpParam.getAppSecret())
                .redirectUri(redirectUri)
                .scopes(Collections.singletonList(newScope))
                .build());
    }

    @Override
    public ThirdAuthUser doLogin(ThirdLoginReq req) {
        ConfigInfo config = configFactory.getConfigOfNonNull(ConfigDefineEnum.WX_MP);
        WxMpParam wxMpParam = BaseConfigParam.jsonToObject(config.getConfigKey(), config.getConfigValue());
        String returnUrl = wxMpParam.getAuthReturnUrl();

        AuthCallback callbackReq = thirdAssembly.toAuthCallback(req);

        @SuppressWarnings("unchecked")
        AuthResponse<AuthUser> login = getAuthRequest("", req.getClient(), wxMpParam, "").login(callbackReq);

        if (!login.ok()) {
            throw new BizException(login.getMsg());
        }

        ThirdAuthUser thirdAuthUser = thirdAssembly.toThirdAuthUser(login.getData());
        thirdAuthUser.setRedirectUrl(returnUrl);
        // 优先以前端为准
        thirdAuthUser.setIsRedirect(false);
        return thirdAuthUser;
    }

    @Override
    public ThirdAuthResp doAuthorize(AuthUrlGetReq req) {
        ConfigInfo config = configFactory.getConfigOfNonNull(ConfigDefineEnum.WX_MP);
        WxMpParam wxMpParam = BaseConfigParam.jsonToObject(config.getConfigKey(), config.getConfigValue());
        AuthRequest authRequest = getAuthRequest(req.getScope(), req.getClient(), wxMpParam, req.getBackUrl());
        String state = AuthStateUtils.createState();
        Assert.notEmpty(req.getBackUrl(), "backUrl 不能为空");
        return ThirdAuthResp.builder().pageUrl(authRequest.authorize(state)).state(state).build();
    }
}
